import 'package:cunyutech_flutter_core/cunyutech_flutter_core.dart';
import 'package:cunyutech_flutter_ui/src/text/main.dart';
import 'package:cunyutech_flutter_ui/src/theme/main.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart' hide RefreshCallback;

import 'SliverListEmpty.dart';
import 'SliverListView.dart';
import 'SliverListViewFooter.dart';
import 'SliverPersistentHeaderChildDelegate.dart';

const double _defaultEndReachedTriggerDistance = 10;

class SliverTableColumn {
  final String field;
  final String title;
  final int flex;
  final Alignment alignment;

  SliverTableColumn({ this.field, this.title, this.flex = 1, this.alignment });
}

typedef Widget SliverTableCellBuilder(BuildContext context, dynamic item, SliverTableColumn column, int rowIndex, int columnIndex);
typedef Widget SliverTableRowBuilder(BuildContext context, dynamic item, List<Widget> children, int rowIndex);
typedef Widget SliverTableHeaderCellBuilder(BuildContext context, SliverTableColumn column, int columnIndex);
typedef Widget SliverTableHeaderBuilder(BuildContext context, List<SliverTableColumn> columns, List<Widget> children);

class SliverTableView extends StatefulWidget {
  /// 渲染表格项
  final SliverTableCellBuilder renderCell;
  /// 渲染行
  final SliverTableRowBuilder renderRow;
  /// 渲染标题
  final SliverTableHeaderCellBuilder renderHeaderCell;
  /// 渲染行
  final SliverTableHeaderBuilder renderHeader;
  /// 所有的配置列
  final List<SliverTableColumn> columns;
   /// 渲染下拉刷新器 可选
  final RefreshControlIndicatorBuilder renderRefresh;
  /// 列表数据
  final List<dynamic> data;
  /// 触发刷新事件 异步 可选
  final RefreshCallback onRefresh;
  /// 触发refresh零界点
  final double refreshIndicatorExtent;
  /// 触发refresh指示器的零界点
  final double refreshTriggerPullDistance;
  /// 触发上拉加载事件
  final EndReachedCallback onEndReached;
  // 触发endReached的零界点
  final double endReachedTriggerDistance;
  /// 列表尾部 可以渲染上拉加载组件
  final Widget footer;
  /// 头部
  final Widget header;
  /// 状态变更
  final EndReachedStateChange onEndReachedStateChange;
  /// 列表背景色，默认为透明色
  final Color backgroundColor;
  /// 内容为空时显示
  final Widget empty;
  /// 外界控制
  final ScrollController controller;
  final PageStorageKey<String> pageStorageKey;
  /// 是否反转
  final bool reverse;
  /// 滑动结束
  final VoidCallback onScrollEnd;
  /// 是否在加载过程中
  final bool firstLoading;
  /// 初次加载的骨架图
  final Widget firstLoadingSkeleton;

  final bool shrinkWrap;

  final String noNetworkIcon;

  static const double _defaultRefreshTriggerPullDistance = 100.0;
  static const double _defaultRefreshIndicatorExtent = 60.0;

  static SliverListViewState of(BuildContext context){
    return context.dependOnInheritedWidgetOfExactType<SliverListViewState>();
  }

  static defaultFooter(bool hasMore) {
    return SliverListViewFooter(
        hasMore: hasMore == true, 
        textStyle: TextStyle(fontSize: CYFontSize.Default),
    );
  }

  static Widget _defaultRenderHeaderCell(BuildContext context, SliverTableColumn column, int columnIndex) {
    return Expanded(
      child: CYParagraph(column.title, fontSize: CYFontSize.Large, alignment: column.alignment),
      flex: column.flex,
    );
  }

  static Widget _defaultRenderHeader(BuildContext context, List<SliverTableColumn> columns, List<Widget> children) {
    return Container(
      height: CYHeight.Large,
      margin: EdgeInsets.symmetric(horizontal: CYMargin.Default),
      child: Row(
        children: children
      )
    );
  }

  static Widget _defaultRenderRow(BuildContext context, dynamic item, List<Widget> children, int rowIndex) {
    return Container(
      margin: EdgeInsets.symmetric(horizontal: CYMargin.Default),
      child: Row(
        children: children
      )
    );
  }

  const SliverTableView({ 
    Key key, 
    @required this.renderCell,
    @required this.data, 
    @required this.columns,
    @required this.noNetworkIcon,
    this.onRefresh,
    this.renderRefresh = CupertinoSliverRefreshControl.buildSimpleRefreshIndicator,
    this.refreshIndicatorExtent = _defaultRefreshIndicatorExtent,
    this.refreshTriggerPullDistance = _defaultRefreshTriggerPullDistance,
    this.footer, 
    this.onEndReached, 
    this.endReachedTriggerDistance = _defaultEndReachedTriggerDistance,
    this.onEndReachedStateChange, 
    this.backgroundColor = Colors.transparent,
    this.header,
    this.empty,
    this.controller,
    this.pageStorageKey,
    this.reverse = false,
    this.shrinkWrap = false,
    this.onScrollEnd,
    this.firstLoading,
    this.firstLoadingSkeleton, 
    this.renderRow = _defaultRenderRow, 
    this.renderHeaderCell = _defaultRenderHeaderCell, 
    this.renderHeader = _defaultRenderHeader,
  }) : super(key: key);

  _SliverTableViewState createState() => _SliverTableViewState();
}

class _SliverTableViewState extends State<SliverTableView> {
  EndReachedState reachedState = EndReachedState.inactive;

  CYNetwork netWorkUtils = CYNetwork();

  bool isFirstLoading = true;
  bool startFirstLoading = false;
  
  @override
  void initState() { 
    super.initState();
    netWorkUtils.check((){
      setState(() {});
    });
  }

  @override
  void dispose() { 
    netWorkUtils.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if(widget.firstLoading == true) {
      return widget.firstLoadingSkeleton;
    }
    bool noData = widget.data == null || widget.data?.length == 0;

    List<Widget> slivers = [];
    if(widget.onRefresh !=null) {
      slivers.add(CupertinoSliverRefreshControl(
        builder: widget.renderRefresh,
        refreshIndicatorExtent: widget.refreshIndicatorExtent,
        refreshTriggerPullDistance: widget.refreshTriggerPullDistance,
        onRefresh: widget.onRefresh,
      ));
    }
    slivers.add(widget.header);
    slivers.add(
      SliverPersistentHeader(
        delegate: SliverPersistentHeaderChildDelegate(
          child: widget.renderHeader(
            context,
            widget.columns,
            widget.columns.map((item)=> widget.renderHeaderCell(context, item, widget.columns.indexOf(item))).toList()
          )
        ),
        pinned: true,
        floating: true,
      ),
    );

    if(netWorkUtils.status != NetWorkStatus.Unknown) {
      slivers.add(
        noData ? widget.empty :
          SliverSafeArea(
            top: false, // Top safe area is consumed by the navigation bar.
            sliver: SliverList(
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) => 
                  widget.renderRow(
                    context, 
                    widget.data.elementAt(index), 
                    widget.columns.map(
                      (column)=> widget.renderCell(
                        context, 
                        widget.data.elementAt(index), 
                        column, 
                        index, 
                        widget.columns.indexOf(column)
                      )
                    ).toList(),
                    index
                  ), 
                childCount: widget.data.length
              ),
            ),
          )
      );
      if(!noData) {
        slivers.add(widget.footer);
      }
    } else {
      slivers.add(SliverListEmpty(
        onTap: widget.onRefresh,
        icon: Image.asset(widget.noNetworkIcon),
        child: CYParagraph("网络连接失败\n请检查您的手机联网状态", maxLines: null, alignment: Alignment.center, color: CYThemeData.of(context).foreColorSystem.secondaryColor, textAlign: TextAlign.center),
      ));
    }
    
    return SliverListViewState(
      reachedState: reachedState,
      context: context,
      child: CupertinoPageScaffold(
        backgroundColor: widget.backgroundColor,
        child: EndReachedNotificationListenerBuilder (
          onScrollEnd: widget.onScrollEnd,
          onEndReached: widget.onEndReached,
          onEndReachedStateChange: (_state) {
            if(widget.onEndReachedStateChange != null) widget.onEndReachedStateChange(_state);
            this.setState(() {
              reachedState = _state;
            });
          },
          child: CustomScrollView(
            key: widget.pageStorageKey,
            reverse: widget.reverse,
            shrinkWrap: widget.shrinkWrap,
            physics: BouncingScrollPhysics(),
            controller: widget.controller,
            slivers: slivers.where((w) => w !=null).toList(),
          ),
        )
      ),
    );
  }
}
